/*
 * Chromossome.cpp
 *
 *  Created on: Jan 9, 2012
 *      Author: luiz
 */
#include <algorithm>
#include <sstream>
#include <iostream>

#include "Chromosome.h"
#include "RandomNumber.h"
#include "Cell.h"
Chromosome::Chromosome(int num_genes)
{
    num_genes_ =num_genes;
}

Chromosome::Chromosome(const Chromosome &chromosome)
{
    this->num_genes_ = chromosome.num_genes_;
    //this->gene_cells_.clear();
    this->gene_cells_ = std::vector<GeneCell>(chromosome.gene_cells_);
    //std::copy(chromosome.gene_cells_.begin(),chromosome.gene_cells_.end(),std::back_inserter(this->gene_cells_));
}

Chromosome & Chromosome::operator =(const Chromosome & chromossome)
{
    if(this != & chromossome){
        this->num_genes_ = chromossome.num_genes_;
        this->gene_cells_ = std::vector<GeneCell>(chromossome.gene_cells_);
    }
    return *this;

}

std::vector<GeneCell> Chromosome::get_gene_cells() const
{
    return this->gene_cells_;
}

void Chromosome::generate_sequencial_gene()
{
    for (int i = 0; i < num_genes_; ++i) {
        gene_cells_.push_back(i);
        gene_cells_[i].set_different_clock(1);
    }
}
// random generator function:
//ptrdiff_t myrandom (ptrdiff_t i) { return RandomNumber::get_instance().getRandomInteger(i);}

// pointer object to it:
//ptrdiff_t (*p_myrandom)(ptrdiff_t) = myrandom;

void Chromosome::generate_random_gene()
{
    generate_sequencial_gene();
    //RandomNumber &random = RandomNumber::get_instance();
    //std::random_shuffle(gene_cells_.begin(),gene_cells_.end(),p_myrandom);
    std::random_shuffle(gene_cells_.begin(),gene_cells_.end());
    for (int i = 0; i < (int)gene_cells_.size(); ++i) {
        gene_cells_[i].set_different_clock(RandomNumber::get_instance().getRandomInteger(2));
    }
}

GeneCell Chromosome::get_cell_by_position(int position)
{
    std::vector<GeneCell>::iterator it = std::find(gene_cells_.begin(),gene_cells_.end(),GeneCell(position));
    if(it != gene_cells_.end()){
        return (*it);
    } else
    {
        return GeneCell();
    }
}
//recebe uma lista com as posicoes ordenadas
void Chromosome::define_gene_order(std::vector<int> gene_ordered)
{
    //para cada poisicao
    for (int i = 0; i < (int)gene_ordered.size(); ++i) {
        // encontrar o iterador para esta posicao no cromossomo
        std::vector<GeneCell>::iterator gene_iterator_source = gene_cells_.begin();
        while(gene_iterator_source != gene_cells_.end()){
            if(gene_iterator_source->position_num() == gene_ordered[i]) break;
            ++gene_iterator_source;
        }
        std::vector<GeneCell>::iterator gene_iterator_destination = gene_cells_.begin()+i;
        std::iter_swap(gene_iterator_source,gene_iterator_destination);
    }
}

void Chromosome::define_gene_different_clock_zone_order(std::vector<int> clock_zone_ordered)
{
    for (int i = 0; i < (int)clock_zone_ordered.size(); ++i) {
        std::vector<GeneCell>::iterator gene_iterator_source = std::find(gene_cells_.begin(),gene_cells_.end(),i);
        gene_iterator_source->set_different_clock(clock_zone_ordered[i]);
    }
}

int Chromosome::get_gene_size()
{
    return gene_cells_.size();
}


Chromosome::~Chromosome(){
  //  std::cout << "\nDESTRUINDO CROMOSSOMO: ";
   // gene_cells_.clear();
    //for (int i = 0; i < gene_cells_.size(); ++i) {
     //   std::cout << gene_cells_[i].position_num() << ",";
   // }
}
//
//bool Chromosome::operator ==(const Chromosome & c) const
//{
//    for (int i = 0; i < (int)gene_cells_.size(); ++i) {
//        if(this->gene_cells_[i].operator !=( c.gene_cells_[i])){
//            return false;
//        }
//    }
//    return true;
//}



bool Chromosome::operator <(const Chromosome & c) const
{
    for (int i = 0; i < (int)this->gene_cells_.size(); ++i)
    {
        if(this->gene_cells_[i].position_num() > c.gene_cells_[i].position_num())
        {
            return false;
        } else if (this->gene_cells_[i].position_num() < c.gene_cells_[i].position_num())
        {
            return true;
        }
    }
    for (int i = 0; i < (int)this->gene_cells_.size(); ++i) {
        if(this->gene_cells_[i].different_clock() > c.gene_cells_[i].different_clock())
        {
            return false;
        } else if(this->gene_cells_[i].different_clock() > c.gene_cells_[i].different_clock())
        {
            return true;
        }
    }
    return false;
}

void Chromosome::set_gene_cells(const std::vector<GeneCell> & gene_cells)
{
    this->gene_cells_ = std::vector<GeneCell>(gene_cells);
}

void Chromosome::set_gene_at_position(int position, const GeneCell & gene_cell)
{
    this->gene_cells_[position] = gene_cell;
}


void Chromosome::swap_gene_cell(int position_origin, int position_destination)
{
    GeneCell cell = this->gene_cells_[position_origin];
    this->gene_cells_[position_destination] = this->gene_cells_[position_origin];
    this->gene_cells_[position_origin] = cell;
}

std::string Chromosome::print_chromosome() const
{
    std::stringstream oss;
    std::cout << "CHROMOSOME SIZE:" << gene_cells_.size() << std::endl;
    oss << "CHROMOSOME SIZE:" << gene_cells_.size() << std::endl;
    for (int i = 0; i < (int)gene_cells_.size(); ++i) {
        oss << gene_cells_[i].position_num() << " " ;
    }
    oss << std::endl;
    for (int i = 0; i < (int)gene_cells_.size(); ++i) {
        oss << gene_cells_[i].different_clock() << " " ;
    }
    return oss.str();
}






